/**********************************************************************************************************
** File name   : Task_Schedule.c
** Author      : Huang Cheng
** Date        : 2021-08-23
** Description : Task_Schedule source file
**********************************************************************************************************/

/**********************************************************************************************************
**                                          头文件引用区
**********************************************************************************************************/
#include "main.h"
#include "Task_Schedule.h"

/**********************************************************************************************************
**                                         全局变量定义区
**********************************************************************************************************/
static TaskIdDef TskIdNum = 0x00;

TaskSchStruct_Typedef TaskSchSt[TASK_MAX_NUM] = 
{
	{NULL, 0, 0, 0, 0},      //Head Node, not regester task
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
	{NULL, 0, 0, 0, 0},
};
/**********************************************************************************************************
**                                           函数声明区
**********************************************************************************************************/
static void TSK_CRITICAL_ENTER(void);
static void TSK_CRITICAL_EXIT(void);

/**********************************************************************************************************
**                                           应用函数区
**********************************************************************************************************/
/**********************************************************************************************************
**	函 数 名 : TSK_CRITICAL_ENTER()
**	功能说明 : 轮询任务进入临界区，即关闭所有中断
**	形    参 : 无
**	返 回 值 : 无
**********************************************************************************************************/
static void TSK_CRITICAL_ENTER(void)
{
	__set_PRIMASK(1);
}

/**********************************************************************************************************
**	函 数 名 : TSK_CRITICAL_EXIT()
**	功能说明 : 轮询任务推出临界区，即开启所有中断
**	形    参 : 无
**	返 回 值 : 无
**********************************************************************************************************/
static void TSK_CRITICAL_EXIT(void)
{
	__set_PRIMASK(0);
}

/**********************************************************************************************************
**	函 数 名 : TaskSchTab_Init()
**	功能说明 : 轮询任务表初始化函数
**	形    参 : 无
**	返 回 值 : 无
**********************************************************************************************************/
TaskFuncDef TaskSchTab_Init(void)
{
	uint8_t i = 0;
	
	for(i = 0; i < (TASK_MAX_NUM-1); i++)
	{
		TaskSchSt[i].AppTskThread = NULL;
		TaskSchSt[i].TskSchTime = 0;
		TaskSchSt[i].TskSchTimeCnt = 0;
		TaskSchSt[i].TskTimeFlg = 0;
		TaskSchSt[i].TskCurNext = i+1;
	}
	
	TaskSchSt[i].AppTskThread = NULL;
	TaskSchSt[i].TskSchTime = 0;
	TaskSchSt[i].TskSchTimeCnt = 0;
	TaskSchSt[i].TskTimeFlg = 0;
	TaskSchSt[i].TskCurNext = 0;
	
	return TASK_TAB_OK;
}

/**********************************************************************************************************
**	函 数 名 : Task_Create()
**	功能说明 : 轮询任务创建函数
**	形    参 : AppTsk - 任务函数地址，TskPollTime - 轮询时间，*TaskId - 任务id
**	返 回 值 : TskIdNum - 注册任务数
**********************************************************************************************************/
TaskFuncDef Task_Create(AppTaskDef (*AppTsk)(void), TaskSchTimeDef TskPollTime, TaskIdDef *TaskId)
{
	uint8_t TempCur = 0x00;
	
	if(((uint8_t)TskIdNum>=TASK_MAX_NUM) || (NULL==AppTsk) || (0x00==TskPollTime))
	{
		return TASK_ID_ERR;
	}
	
	TempCur = TaskSchSt[TASK_QUEUE_HEAD].TskCurNext;
	TaskSchSt[TempCur].AppTskThread = AppTsk;
	TaskSchSt[TempCur].TskSchTime = TskPollTime;
	*TaskId =  TempCur;
	
	TaskSchSt[TASK_QUEUE_HEAD].TskCurNext = TaskSchSt[TempCur].TskCurNext;
	
	TskIdNum++;
	
	return TASK_ID_OK;
}

/**********************************************************************************************************
**	函 数 名 : Task_Delete()
**	功能说明 : 轮询任务删除函数
**	形    参 : *TskId - 待删除的任务ID
**	返 回 值 : TASK_ID_ERR - 删除失败，TASK_ID_OK - 删除成功
**********************************************************************************************************/
TaskFuncDef Task_Delete(TaskIdDef *TskId)
{
	if((TASK_ID_DEL==*TskId) || (TskIdNum <= 0x00))
	{
		return TASK_ID_ERR;
	}
	
	/* 清除当前Id在任务队列中的参数，并修改游标指向值 */
	TaskSchSt[*TskId].AppTskThread = NULL;
	TaskSchSt[*TskId].TskSchTime = 0x00;
	TaskSchSt[*TskId].TskSchTimeCnt = 0x0000;
	TaskSchSt[*TskId].TskTimeFlg = 0x00;
	
	TaskSchSt[*TskId].TskCurNext = TaskSchSt[TASK_QUEUE_HEAD].TskCurNext;
	TaskSchSt[TASK_QUEUE_HEAD].TskCurNext = *TskId;
	
	/* TaskId在进行删除操作后需标记为已删除的ID */
	*TskId = TASK_ID_DEL;
	TskIdNum--;
	
	return TASK_ID_OK;
}

/**********************************************************************************************************
**	函 数 名 : GetTaskCurtNum()
**	功能说明 : 获取当前任务数函数（解耦函数且可以保护当前任务数不被篡改）
**	形    参 : 无
**	返 回 值 : TskIdNum - 当前队列中有效任务数
**********************************************************************************************************/
TaskIdDef GetTaskCurtNum(void)
{
	return TskIdNum;
}

/**********************************************************************************************************
**	函 数 名 : SetTaskSchTime()
**	功能说明 : 设置当前任务轮询时间（解耦函数且可以保护当前任务数不被篡改）
**	形    参 : TskId - 任务id， TaskTime - 轮询时间
**	返 回 值 : 无
**********************************************************************************************************/
void SetTaskSchTime(TaskIdDef TskId, TaskSchTimeDef TaskTime)
{
	TaskSchSt[TskId].TskSchTime = TaskTime;
}

/**********************************************************************************************************
**	函 数 名 : Task_Timer_CallBack()
**	功能说明 : 任务定时标志位设定回调函数，被1ms时基的定时器中断函数调用
**	形    参 : 无
**	返 回 值 : 无
**********************************************************************************************************/
AppTaskDef Task_Timer_CallBack(void)
{
	uint8_t TskNum = 0x00;
	
	/* 进入临界区 */
	TSK_CRITICAL_ENTER();
	
	/* 队列头节点不存储任务，无需轮询 */
	for(uint8_t TskNum = 0x01; TskNum < TASK_MAX_NUM; TskNum++)
	{
		if(NULL == TaskSchSt[TskNum].AppTskThread)
		{
			continue;
		}
		
		TaskSchSt[TskNum].TskSchTimeCnt++;
		if(TaskSchSt[TskNum].TskSchTimeCnt >= TaskSchSt[TskNum].TskSchTime)
		{
			TaskSchSt[TskNum].TskSchTimeCnt = 0x00;
			TaskSchSt[TskNum].TskTimeFlg = TASK_FLAG_SET;
		}
		else
		{
			//do nothig;
		}
	}
	
	/* 退出临界区 */
	TSK_CRITICAL_EXIT();
}
/**********************************************************************************************************
**	函 数 名 : Task_Schedule_Handler()
**	功能说明 : 轮询任务处理回调函数
**	形    参 : 无
**	返 回 值 : 无
**********************************************************************************************************/
AppTaskDef Task_Schedule_Handler(void)
{
	uint8_t TskNum = 0x00;
	
	/* 队列头节点不存储任务，无需轮询 */
	for(TskNum = 0x01; TskNum < TASK_MAX_NUM; TskNum++)
	{
		if(TASK_FLAG_SET != TaskSchSt[TskNum].TskTimeFlg)
		{
			continue;
		}
		
		if(NULL != TaskSchSt[TskNum].AppTskThread)
		{
			TaskSchSt[TskNum].AppTskThread();
			TaskSchSt[TskNum].TskTimeFlg = TASK_FLAG_RESET;
		}
		else
		{
			//do nothing;
		}
	}
}

/**********************************************************************************************************
**                                          End Of File
**********************************************************************************************************/